package main

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"encoding/base64"
	"fmt"
	"io"
	"log"
	"os"
)

const (
	algorithm      = "AES"
	transformation = "AES/GCM/NoPadding"
	key            = "dG9wd2Fsa2FkbWluMTIzNA==" // replace with your actual key
)

func main() {
	originalFilePath := "C:\\Users\\pc\\Desktop\\topwalk_web_attack_all_3000_20240428.rules"
	encryptedFilePath := "C:\\Users\\pc\\Desktop\\topwalk_web_attack_all_3000_20240428.enc"
	decryptedFilePath := "C:\\Users\\pc\\Desktop\\topwalk_web_attack_all_3000_20240428.txt"

	// Encrypt file
	err := encryptFileGCM(originalFilePath, encryptedFilePath)
	if err != nil {
		log.Fatal(err)
	}

	// Decrypt file
	err = decryptFileGCM(encryptedFilePath, decryptedFilePath)
	if err != nil {
		log.Fatal(err)
	}
}

func encryptFileGCM(inputFileName, outputFileName string) error {
	keyBytes, err := base64.StdEncoding.DecodeString(key)
	if err != nil {
		return err
	}

	plaintext, err := os.ReadFile(inputFileName)
	if err != nil {
		return err
	}

	block, err := aes.NewCipher(keyBytes)
	if err != nil {
		return err
	}

	aesGCM, err := cipher.NewGCM(block)
	if err != nil {
		return err
	}

	nonce := make([]byte, aesGCM.NonceSize())
	if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
		return err
	}

	ciphertext := aesGCM.Seal(nil, nonce, plaintext, nil)

	f, err := os.Create(outputFileName)
	if err != nil {
		return err
	}
	defer f.Close()

	_, err = f.Write(nonce)
	if err != nil {
		return err
	}

	_, err = f.Write(ciphertext)
	if err != nil {
		return err
	}

	return nil
}

func decryptFileGCM(inputFileName, outputFileName string) error {
	keyBytes, err := base64.StdEncoding.DecodeString(key)
	if err != nil {
		return err
	}

	ciphertext, err := os.ReadFile(inputFileName)
	if err != nil {
		return err
	}

	block, err := aes.NewCipher(keyBytes)
	if err != nil {
		return err
	}

	aesGCM, err := cipher.NewGCM(block)
	if err != nil {
		return err
	}

	nonceSize := aesGCM.NonceSize()
	if len(ciphertext) < nonceSize {
		return fmt.Errorf("ciphertext too short")
	}

	nonce, ciphertext := ciphertext[:nonceSize], ciphertext[nonceSize:]

	plaintext, err := aesGCM.Open(nil, nonce, ciphertext, nil)
	if err != nil {
		return err
	}

	f, err := os.Create(outputFileName)
	if err != nil {
		return err
	}
	defer f.Close()

	_, err = f.Write(plaintext)
	if err != nil {
		return err
	}

	return nil
}
